/**
  ******************************************************************************
  * @file    common_include.h
  * @author  ashuai0110
  * @version V2.3
  * @date    2024-07-01
  * @brief   公共引用文件(所有组件都需包含此文件)
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module.git
  *
  ******************************************************************************
  */

#ifndef __COMMON_INCLUDE_H
#define __COMMON_INCLUDE_H

#ifdef __cplusplus
extern "C" {
#endif

/* 包含头文件-----------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>

/**
 * @addtogroup common
 * @{
 */

/**
 * @defgroup common_include common_include
 * @{
 */

/* 宏定义---------------------------------------------------------------------*/
/**
 * @defgroup common_include_global_macros common include global macros
 * @{
 */

#define _USE_PRINT_LOG                          (1u) /*!< 打印接口开关 0:关闭 1:打开 */
#define _USE_ASSERT_PARAM                       (1u) /*!< 参数检查开关 0:关闭 1:打开 */
#define _USE_TIME_STAMP                         (1u) /*!< 时间戳相关内容开关 0:关闭 1:打开 */

/**
 * @defgroup generic_error_codes generic error codes
 * @{
 */
#define RET_OK                                  (0u) /*!< 成功,完成 */
#define RET_ERR                                 (1u) /*!< 失败,错误 */
#define RET_ING                                 (2u) /*!< 进行中 */
#define RET_TIMEOUT                             (3u) /*!< 超时 */
#define RET_FULL                                (4u) /*!< 已满/溢出 */
#define RET_LEN_ERR                             (5u) /*!< 长度错误 */
#define RET_CHECK_ERR                           (6u) /*!< 校验错误 */
#define RET_FRAME_ERR                           (7u) /*!< 格式错误 */
/**
 * @}
 */

/**
 * @defgroup print_log_macros print log macros
 * @{
 */
#if _USE_PRINT_LOG
/* 用户引入头文件并修改PRINT_LOG宏定义内容以对接打印接口 */
#include "SEGGER_RTT.h"
  /* 普通级别日志输出 */
  #ifndef PRINT_LOG
    #define PRINT_LOG(fmt, args...)             do { \
                                                SEGGER_RTT_printf(0, fmt, ##args); \
                                                }while(0)
  #endif
#else
  #ifndef PRINT_LOG
    #define PRINT_LOG(fmt, args...)             ((void)0)
  #endif
#endif
/* DEBUG级别日志输出 */
#ifndef DEBUG_LOG
  #define DEBUG_LOG(fmt, args...)               do { \
                                                PRINT_LOG("[%s:%d]DEBUG: "fmt"\r\n",__FILE__,__LINE__,##args); \
                                                }while(0)
#endif
/* WARN级别日志输出 */
#ifndef WARN_LOG
  #define WARN_LOG(fmt, args...)                do { \
                                                PRINT_LOG("[%s:%d]WARN: "fmt"\r\n",__FILE__,__LINE__,##args); \
                                                }while(0)
#endif
/* ERROR级别日志输出 */
#ifndef ERROR_LOG
  #define ERROR_LOG(fmt, args...)               do { \
                                                PRINT_LOG("[%s:%d]ERROR: "fmt"\r\n",__FILE__,__LINE__,##args); \
                                                }while(0)
#endif
/* 版本信息日志输出 */
#ifndef VERSION_LOG
#define VERSION_LOG(n, m, s, p)                 do { \
                                                PRINT_LOG("Project: %s, Version: %d.%d.%d, Build Time: %s %s\r\n",n,m,s,p,__DATE__,__TIME__); \
                                                }while(0)
#endif
/**
 * @}
 */

/**
 * @defgroup interrupt_control_macros interrupt control macros
 * @brief    中断控制相关
 * @note     若MCU不适用此处需用户修改
 * @{
 */
/* 开启全局中断 */
#ifndef ENABLE_GLOBAL_INTERRUPT
  #define ENABLE_GLOBAL_INTERRUPT()             do { \
                                                __asm volatile ("cpsie i"); \
                                                }while(0)
#endif
/* 关闭全局中断 */
#ifndef DISABLE_GLOBAL_INTERRUPT
  #define DISABLE_GLOBAL_INTERRUPT()            do { \
                                                __asm volatile ("cpsid i"); \
                                                }while(0)
#endif
/* 原子操作(全局中断) */
#ifndef ATOM_CODE
  #define ATOM_CODE(...)                        do { \
                                                DISABLE_GLOBAL_INTERRUPT(); \
                                                __VA_ARGS__; \
                                                ENABLE_GLOBAL_INTERRUPT(); \
                                                }while(0)
#endif

#if defined (__CC_ARM)
/* 临界区上锁 */
#define CRITICAL_LOCK()                         { \
                                                unsigned int lockState; \
                                                register unsigned char BASEPRI __asm( "basepri"); \
                                                lockState = BASEPRI; \
                                                BASEPRI = 0x20;
/* 临界区解锁 */
#define CRITICAL_UNLOCK()                       BASEPRI = lockState; \
                                                }
#else
#define CRITICAL_LOCK()                         ((void)0)
#define CRITICAL_UNLOCK()                       ((void)0)
#endif
/**
 * @}
 */

/**
 * @defgroup complex_type_macros complex type macros
 * @brief    复杂类型相关操作
 * @{
 */
/* 数组的数量 */
#ifndef ARRAY_NUM
  #define ARRAY_NUM(arr)                        (sizeof((arr)) / sizeof((arr)[0]))
#endif
/* 结构体清零 */
#ifndef MEM_ZERO_STRUCT
  #define MEM_ZERO_STRUCT(str)                  do { \
                                                memset((void *)&(str), 0u, (sizeof(str))); \
                                                }while(0)
#endif
/**
 * @}
 */

/**
 * @defgroup integer_type_macros integer type macros
 * @brief    整数类型相关操作
 * @{
 */
/* 两者最大值 */
#ifndef MAX
  #define MAX(a, b)                             ((a) > (b) ? (a) : (b))
#endif
/* 两者最小值 */
#ifndef MIN
  #define MIN(a, b)                             ((a) < (b) ? (a) : (b))
#endif
/* 向上整数对齐 ALIGN_UP(13,4)=16 */
#ifndef ALIGN_UP
  #define ALIGN_UP(num, align)                  (((num) + (align) - 1) & ~((align) - 1))
#endif
/* 向下整数对齐 ALIGN_DOWN(13,4)=12 */
#ifndef ALIGN_DOWN
  #define ALIGN_DOWN(num, align)                ((num) & ~((align) - 1))
#endif
/* 十进制转换BCD码 DEC2BCD(10)=0x10 */
#ifndef DEC2BCD
  #define DEC2BCD(val)                          ((((val) / 10u) << 4u) + ((val) % 10u))
#endif
/* BCD码转换十进制 BCD2DEC(0x10)=10 */
#ifndef BCD2DEC
  #define BCD2DEC(val)                          ((((val) >> 4u) * 10u) + ((val) & 0x0Fu))
#endif
/**
 * @}
 */

/**
 * @defgroup bit_type_macros bit type macros
 * @brief    位相关操作
 * @{
 */
/* 置位 BIT_SET(0x10,0)=0x11 */
#ifndef BIT_SET
  #define BIT_SET(val, bitx)                    ((val) | (1u << (bitx)))
#endif
/* 复位 BIT_RESET(0x11,0)=0x10 */
#ifndef BIT_RESET
  #define BIT_RESET(val, bitx)                  ((val) & ~(1u << (bitx)))
#endif
/* 读取位 BIT_READ(0x11,4)=0x10 */
#ifndef BIT_READ
  #define BIT_READ(val, bitx)                   ((val) & (1u << (bitx)))
#endif
/* 翻转位 BIT_TOGGLE(0x10,0)=0x11 */
#ifndef BIT_TOGGLE
  #define BIT_TOGGLE(val, bitx)                 ((val) ^ (1u << (bitx)))
#endif
/* 替换位 BIT_REPLACE(0xF0,0x03,0)=0xF1 BIT_REPLACE(0x0F,0xFE,0)=0x0E */
#ifndef BIT_REPLACE
  #define BIT_REPLACE(sVal, dVal, num)          (((sVal) & (~(1u << (num)))) | ((dVal) & (1u << (num))))
#endif
/**
 * @}
 */

/**
 * @defgroup memory_read_write_macros memory read write macros
 * @brief    内存相关操作
 * @{
 */
/* 以内存地址读写1字节 RAM-R/W ROM-R */
#ifndef RW_RAM8
  #define RW_RAM8(addr)                         (*(char *)(unsigned int)(addr))
#endif
/* 以内存地址读写2字节 RAM-R/W ROM-R */
#ifndef RW_RAM16
  #define RW_RAM16(addr)                        (*(short *)(unsigned int)(addr))
#endif
/* 以内存地址读写4字节 RAM-R/W ROM-R */
#ifndef RW_RAM32
  #define RW_RAM32(addr)                        (*(int *)(unsigned int)(addr))
#endif
/**
 * @}
 */

/**
 * @defgroup parameter_check_macros parameter check macros
 * @{
 */
#if _USE_ASSERT_PARAM
  /* 参数检查 */
  #ifndef ASSERT_PARAM
    #define ASSERT_PARAM(x)                     do{ \
                                                if(!x) { \
                                                ERROR_LOG("!!!wrong param!!!"); \
                                                while(1); \
                                                } \
                                                }while(0)
  #endif
#else
  #ifndef ASSERT_PARAM
    #define ASSERT_PARAM(x)                     ((void)0)
  #endif
#endif
/* 指针有效性检查 */
#define IS_VALID_POINT(p)                       ((p) != NULL)
/**
 * @}
 */

/**
 * @defgroup weak_function_define weak function define
 * @brief    弱函数定义
 * @{
 */
#if defined (__GNUC__) && !defined (__CC_ARM) /*!< GNU Compiler */
  #ifndef __WEAK
    #define __WEAK                              __attribute__((weak))
  #endif
#elif defined (__ICCARM__) /*!< IAR Compiler */
  #ifndef __WEAK
    #define __WEAK                              __weak
  #endif
#elif defined (__CC_ARM) /*!< ARM Compiler */
  #ifndef __WEAK
    #define __WEAK                              __attribute__((weak))
  #endif
#else
  #error  "unsupported compiler!"
#endif
/**
 * @}
 */

/**
 * @}
 */

/* 类型定义-------------------------------------------------------------------*/
/**
 * @defgroup common_include_global_types common include global types
 * @{
 */

/**
  * @brief  常用普通函数类型
  *
  * @param  None
  *
  * @retval None
  */
typedef void (* module_normal_fn_t)(void);

/**
  * @brief  常用读写数据类型
  *
  * @param  data : 写入数据的存储区 / 读取数据的存储区
  *
  * @param  len  : 写入的数据大小 / 读取的数据大小 byte
  *
  * @retval 实际写入的数据大小 / 实际读取的数据大小 byte
  */
typedef uint32_t (* module_read_write_fn_t)(void *data, uint32_t len);

/**
  * @brief  组件时间 structure definition
  */
#if _USE_TIME_STAMP
typedef struct module_time {
    uint16_t year;  /*!< 年 20xx */
    uint8_t month;  /*!< 月 1~12 */
    uint8_t day;    /*!< 日 1~31 */
    uint8_t week;   /*!< 周 1~7 */
    uint8_t hour;   /*!< 时 0~23 */
    uint8_t minute; /*!< 分 0~59 */
    uint8_t second; /*!< 秒 0~59 */
} module_time_t;
#endif

/**
 * @}
 */

/* 全局变量-------------------------------------------------------------------*/

/* 函数原型-------------------------------------------------------------------*/
/**
 * @addtogroup common_include_global_functions
 * @{
 */

void module_tick_inc(uint32_t ticks);
uint32_t module_tick_get(void);

#if _USE_TIME_STAMP
void module_time_stamp_init(uint32_t baseTime);
void module_time_stamp_1s(void);
uint32_t module_time_stamp_get(void);

uint32_t module_time_stamp_conv(module_time_t moduleTime);
void module_time_std_conv(module_time_t *_time, uint32_t timeStamp);
void module_time_sntp_conv(module_time_t *_time, char *sntpTime);
#endif

/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */

#ifdef __cplusplus
}
#endif

#endif /* common_include.h */
